<?php
/**
 * Created by PhpStorm.
 * User: DELL-PC
 * Date: 2018/8/2
 * Time: 20:44
 */

namespace Aoe\Emulator\Processor;

use Aoe\Database\Operator;
use Aoe\Database\Sprite;
use Aoe\Emulator\Ifc\Key;
use Aoe\Emulator\Ifc\Type;
use Aoe\Emulator\Pascal\PascalProvider;
use PDO;
use Throwable;

/**
 * # Where条件语句
 */
class Condition extends Processor
{
    /**
     * ## 编译查询数组
     *
     * @param array<scalar | Sprite | array{operator?: string, value?: mixed, name: string}> | int $terms
     *
     * @return null | Sprite[]
     */
    public function make(array | int $terms): ?array
    {
        // { id | ids }
        if (convert_ids($terms)) {
            try {
                return [
                    new Sprite(
                        is_array($terms) ? Operator::IN_OPERATOR : '=',
                        $terms,
                        PDO::PARAM_INT,
                        Type::ID,
                    ),
                ];
            } catch (Throwable) {
            }
            return null;
        }

        $r = [];
        foreach ($terms as $index => $object) {
            //  { Sprite }
            if ($object instanceof Sprite) {
                $r[] = $object;
                continue;
            }
            
            if (is_int($index)) {
                if (!is_array($object) || !isset($object[Key::NAME])) continue;
                
                $name       = $object[Key::NAME];
                $instructor = $object[Key::OPERATOR] ?? null;
                $value      = $object[Key::VALUE] ?? null;
            } else {
                $name       = $index;
                $instructor = null;
                $value      = $object;
            }
            // 内置数据格式不处理
            if (in_array($name[0], ['#', '&', '$', '@'])) continue;
            // 空字符串不查询
            if ($instructor === '=' && $value === '') continue;
            // TODO 关联相似
            if ($instructor === Operator::AS_OPERATOR) continue;
            
            // 正常情况
            try {
                $r[] = PascalProvider::get($this->model->getElement($name))->compare($value, $instructor);
                continue;
            } catch (Throwable) {
            }
        }
        
        return $r;
    }
}